﻿using System;
using System.Collections.Generic;
using SdmxMl.Structure;
using SdmxMl.Common;
using SdmxMl.Manager;

using System.Text;

namespace ActivityMgr.HGDE
{
    public class Communes
    {
        private DateTime defaultValidFromDate;
        private SmManager sm;
        private Dictionary<string, CodeListType> dicoClRef;
        public ValidityCodelist validityList;
        private HierarchicalCodelistType hcl;

        public Communes(string hgdeFullId)
        {
            sm = new SmManager();
            hcl = sm.GetArtefact(SdmxArtefactType.HierarchicalCodelists, new ArtefactRefBase(hgdeFullId), true) as HierarchicalCodelistType;
            dicoClRef = GetRefDictionary(hcl.HierarchyList[0]);

            validityList = new ValidityCodelist(dicoClRef["GDE"].CodeList.Count);

            // Determine default start time
            try
            {
                defaultValidFromDate = DateTime.Parse(hcl.ValidFrom);
            }
            catch
            {
                throw new ApplicationException("No valid attribute 'ValidFrom' defined in hierarchy");
            }


            TreeRecurse(hcl.HierarchyList[0].CodeRefList, 0, null);

            // now links
            validityList.UpdateLinks();


        }

        private void TreeRecurse(CodeRefTypeList orgList, int level, CodeType parentCode)
        {
            foreach (CodeRefType crt in orgList)
            {
                CodeListType clt = dicoClRef[crt.CodelistAliasRef];
                CodeType c = clt.CodeList.LocateItem(crt.CodeID) as CodeType;
                if (c == null)
                    throw new ApplicationException("Undiscoverable code: " + crt.CodeID);

                if (level == 2) // municipalities
                {

                    DateTime dtFrom, dtTo;
                    DetermineLimitsDate(crt, out dtFrom, out dtTo);

                    ValidityCode vc = new ValidityCode(dtFrom, dtTo, c);
                    validityList.Add(vc);
                }

                    // Recurse
                    TreeRecurse(crt.CodeRefList, level + 1, c);
            }

        }

        /// <summary>
        /// Obtains valid from and valid to dates, set default values if not defined
        /// </summary>
        /// <param name="crt">the code reference info holding validity limits</param>
        /// <param name="dtFrom">the valid from date result</param>
        /// <param name="dtTo">the valid to date result</param>
        private void DetermineLimitsDate(CodeRefType crt, out DateTime dtFrom, out DateTime dtTo)
        {
            try
            {
                dtFrom = DateTime.MaxValue;
                if (string.IsNullOrEmpty(crt.ValidFrom) == false)
                    dtFrom = Convert.ToDateTime(crt.ValidFrom);
                else
                    dtFrom = defaultValidFromDate;

                dtTo = DateTime.MaxValue;
                if (string.IsNullOrEmpty(crt.ValidTo) == false)
                    dtTo = Convert.ToDateTime(crt.ValidTo);
            }
            catch
            {
                throw new ApplicationException("Invalid Date format in ValidFrom / ValidTo attributes.");
            }
        }

        #region Ref Dictionary

        private Dictionary<string, CodeListType> GetRefDictionary(HierarchyType heType)
        {
            Dictionary<string, CodeListType> dico = new Dictionary<string, CodeListType>();

            foreach (CodelistRefType crt in heType.CodelistRefList)
            {
                CodeListType clType = null;
                ArtefactRefBase arb = new ArtefactRefBase(crt.Id, crt.AgencyId, crt.Version);
                clType = sm.GetArtefact(SdmxArtefactType.CodeLists, arb, true) as CodeListType;
                if (clType != null)
                    dico.Add(crt.Alias, clType);
                else
                    throw new ApplicationException("Invalid CodelistRef, not found: " + arb.FullIdent);
            }

            return dico;
        }

        #endregion

    }
}
